Editor's Note:
Around mid-November in the Liberty BASIC discussion group at the Conforums site, there was a discussion about the best way to align numbers within various types of controls. Many participants agreed that the best way was to use a fixed-width font in a Liberty BASIC TEXTBOX or TEXTEDITOR control. Bill Jennings wrote the following demo to show that non-fixed-width fonts can be aligned quite nicely.
Thanks, Bill!

Screenshot: Decimal alignment shown
' alignNumbers.bas
' Align with non-fixed font in a
' textbox, texteditor, or graphicbox
' by the numbers' left end, right end,
' or decimal point.
' Bill Jennings, November 2003
nomainwin
wTb=200 'width of textbox
wTe=314 'width of texteditor
wGb=314 'width of graphicbox
WindowWidth=640 : WindowHeight=480
statictext #w1.st1, "Textbox -->",136,6,60,16
statictext #w1.st2a, "Texteditor",80,30,200,16
statictext #w1.st2b, "Graphicbox",440,30,200,16
statictext #w1.st3, "Align:",40,394,40,24
button #w1.b1, "left",[left],UL,80,390
button #w1.b2, "right",[right],UL,155,390
button #w1.b3, "decimal",[decimal],UL,240,390
button #w1.b4, "quit",[quit],UL,360,390
textbox #w1.tb1, 200,0,wTb,30
texteditor #w1.te1, 1,46,wTe,340
graphicbox #w1.g1, 318,46,wGb,340
open "" for window as #w1
print #w1, "trapclose [quit]"
print #w1.g1, "down"
fontSize=18
print #w1.g1, "font Arial 0 ";fontSize
print #w1.tb1, "!font Arial 0 ";fontSize
print #w1.te1, "!font Arial 0 ";fontSize
gosub [getNumbers]
gosub [getStringwidths]
goto [left] 'Show left alignment to start.
[quit]
close #w1
END
[left]
'left alignment is automatic in the textbox:
print #w1.tb1, "" 'clear textbox
numTxtBox=int(rnd(1)*16)+1 'random index --
'use it for [right] & [decimal] modules
print #w1.tb1, n$(numTxtBox)
'and the texteditor:
print #w1.te1, "!cls" 'clear texteditor
for j=1 to nNum
print #w1.te1, n$(j)
next j
'as well as the graphicbox:
gosub [initGraphicbox]
for j=1 to nNum
print #w1.g1, "\";n$(j)
next j
WAIT
[right]
'textbox:
print #w1.tb1, "" 'clear textbox
a$=n$(numTxtBox) : wA=wNum(numTxtBox)
'accumulate spaces to make a left margin
cor1=-16 '*** see Note 1 at end of code
cor2=int(wA/40) '*** see Note 2 at end of code
while wA < wTb+cor1+cor2
a$=" "+a$
wA=width(a$) 'See Function at end of code
wend
print #w1.tb1, a$
'texteditor:
print #w1.te1, "!cls" 'clear texteditor
for j=1 to nNum
a$=n$(j) : wA=wNum(j)
'accumulate spaces to make a left margin
cor1=-23 '*** see Note 1 at end of code
cor2=int(wA/40) '*** see Note 2 at end of code
while wA < wTe+cor1+cor2
a$=" "+a$
wA=width(a$) 'See Function at end of code
wend
print #w1.te1, a$
next j
'graphicbox:
gosub [initGraphicbox]
for j=1 to nNum
wA=wNum(j) : xPos=wGb-wA-4 'horizontal position
yPos=j*fontSize 'vertical position
print #w1.g1, "place ";xPos;" ";yPos
print #w1.g1, "\";n$(j)
next j
WAIT
[decimal]
'textbox:
print #w1.tb1, "" 'clear textbox
decPos=int(wTb/2) 'position decimal point
a$=n$(numTxtBox)
p=instr(a$,".")
lf$=left$(a$,p) : rt$=mid$(a$,p+1)
wL=wLf(numTxtBox)
'accumulate spaces to make a left margin
cor1=-16 '*** see Note 1 at end of code
cor2=int(wL/40) '*** see Note 2 at end of code
while wL < decPos+cor1+cor2
lf$=" "+lf$
wL=width(lf$) 'See Function at end of code
wend
print #w1.tb1, lf$+rt$
'texteditor:
print #w1.te1, "!cls" 'clear texteditor
decPos=int(wGb/2) 'position decimal point
for j=1 to nNum
p=instr(n$(j),".")
lf$=left$(n$(j),p) : rt$=mid$(n$(j),p+1)
wL=wLf(j)
'accumulate spaces to make a left margin
cor1=-23 '*** see Note 1 at end of code
cor2=int(wL/40) '*** see Note 2 at end of code
while wL < decPos+cor1+cor2
lf$=" "+lf$
wL=width(lf$) 'See Function at end of code
wend
print #w1.te1, lf$+rt$
next j
'graphicbox:
gosub [initGraphicbox]
decPos=int(wGb/2) 'position decimal point
for j=1 to nNum
wL=wLf(j)
xPos=decPos-wL
yPos=j*fontSize 'vertical position
print #w1.g1, "place ";xPos;" ";yPos
print #w1.g1, "\";n$(j)
next j
WAIT
[initGraphicbox]
print #w1.g1, "fill 207 248 226"
print #w1.g1, "backcolor 207 248 226"
print #w1.g1, "color darkpink"
print #w1.g1, "down; place 1 18"
RETURN
[getNumbers] 'Make an assortment of random numbers.
'If a number is an integer or zero,
' tack on a decimal point.
nNum=16
DIM n$(nNum)
for j=1 to nNum
mul=3^j
n=int(rnd(1)*mul+1)/14
Select Case n
Case int(n) 'n is an integer
ntg=1 'flag integer
n$(j)=str$(n)+"."
Case 0 'n is zero
n$(j)=str$(n)+".0"
Case Else
n$(j)=str$(n)
End Select
next j
'If no integer in the group, create one.
if not(ntg) then
for j=1 to nNum
if val(n$(j)) > 0 then
n$(j)=str$(int(val(n$(j))))+"."
j=29
end if
next j
end if
RETURN
[getStringwidths]
DIM wNum(nNum) 'entire width (pixels)
DIM wLf(nNum) 'width left of decimal
for j=1 to nNum
wNum(j)=width(n$(j)) 'See Function below.
p=instr(n$(j),".") 'find decimal position
wLf(j)=width(left$(n$(j),p-1)) 'width of
'left side of number string
next j
RETURN
Function width(aString$) 'See 'stringwidth?'
'command in the LB3 helpfile.
print #w1.g1, "stringwidth? aString$ width"
End Function
'NOTES:
'*** Note 1 (does not apply to graphicbox):
' cor1 is a correction factor for justification
' that must be determined by trial and error.
' It is different for various fonts and sizes, and
' depends on the width of the textbox or texteditor.
' Some other values for cor1:
' fontSize cor1
' 10 274
' 12 80
' 16 -20
' 24 -120
' 36 -184
'*** Note 2 (does not apply to graphicbox):
' cor2 is a correction factor for the length of
' the number string. It also must be determined
' by trial and error.
'*** Additional notes:
' I tried to derive an equation for the
' correction for various font sizes, but
' my results were only approximate and
' unsatisfactory.
' ALIGNMENT IN GRAPHICS IS STRAIGHTFORWARD
' (REQUIRES NO CORRECTIONS)!